﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;
using MefContrib.Integration.Unity;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.Collections;
using System.ComponentModel.Composition;
using System.Resources;

namespace SkeletonNET.Common.Setup
{
    public static class Bootstrapper
    {
        public static ApplicationBootstrapper Current
        {
            get { return new ApplicationBootstrapper(); }
        }

        public class ApplicationBootstrapper
        {
            protected bool IsBuild { get; set; }
            protected IUnityContainer Container { get; set; }

            [ImportMany(typeof(ISetup))]
            public IEnumerable<Lazy<ISetup>> Setups { get; set; }

            /// <summary>
            /// Setup the IoC container
            /// </summary>
            /// <returns>Current instance of ApplicationBootstrapper</returns>
            public virtual ApplicationBootstrapper SetupIoC()
            {
                var container = new UnityContainer();
                ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
                container.RegisterInstance<IUnityContainer>(container)
                         .RegisterCatalog(new AssemblyCatalog(Assembly.GetCallingAssembly()));
                container.RegisterCatalog(new DirectoryCatalog("."));
                this.Container = container;
                this.RegisterDefaults();

                return this;
            }

            /// <summary>
            /// Will call the setup method on each IBlock implementation
            /// </summary>
            /// <returns>Current instance of ApplicationBootstrapper</returns>
            public virtual ApplicationBootstrapper SetupModules()
            {
                if (!IsBuild)
                    ServiceLocator.Current.GetInstance<IUnityContainer>().BuildUp(this);

                // Call setup() methods
                Setups
                    .AsParallel()
                    .ForAll(x => x.Value.Setup());

                return this;
            }

            protected virtual void RegisterDefaults()
            {
                // Register a default ResourceManager
                //this.Container.RegisterType<ResourceManager, ResourceManager>();
            }
        }
    }
}